package com.yantong.service.impl;

import com.yantong.utils.PageUtils;
import com.yantong.pojo.RolePerm;
import com.yantong.pojo.SysRole;
import com.yantong.mapper.RoleMapper;
import com.yantong.mapper.RolePermMapper;
import com.yantong.mapper.UserMapper;
import com.yantong.mapper.UserRoleMapper;
import com.yantong.service.RoleService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;


/**
 * 角色操作
 * @author kanghaixin
 */
@Service
public class RoleServiceImpl implements RoleService {
    private static final String ROLE_CACHE_NAME = "role";
    private static final String MENU_CACHE_NAME = "menu";
    private static final Logger logger = LoggerFactory.getLogger(RoleServiceImpl.class);

    @Autowired
    RoleMapper roleMapper;
    @Autowired
    RolePermMapper rolePermMapper;
    @Autowired
    UserMapper userMapper;
    @Autowired
    UserRoleMapper userRoleMapper;

    /**
     *
     * @param params
     * @return
     */
    @Override
    @Cacheable(value = ROLE_CACHE_NAME, keyGenerator = "localKeyGenerator")
    public List<SysRole> listRoles(HashMap<String,Object> params) {
        return roleMapper.getListByParams(params);
    }

    @Override
    @Cacheable(value = ROLE_CACHE_NAME,keyGenerator = "localKeyGenerator")
    public PageUtils<SysRole> listRoles(HashMap<String, Object> params, Integer offset, Integer limit) {
        PageUtils<SysRole> pageUtils = new PageUtils<>();
        int total = roleMapper.countByParams(params);
        if (total > 0) {
            List<SysRole> list = roleMapper.getListByParams(params, new RowBounds(offset, limit));
            pageUtils.setRows(list);
            pageUtils.setTotal(total);
        }
        return pageUtils;
    }

    @CacheEvict(value = ROLE_CACHE_NAME, allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int saveRole(SysRole role) {
        if (role == null) {
            logger.info("save role is null");
            return 0;
        }
        int result = roleMapper.insert(role);
        if (role.getRoleId() == null) {
            return 0;
        }

        List<RolePerm> rolePerms = new ArrayList<>();

        List<Long> menuIds = role.getMenuIds();
        if (CollectionUtils.isNotEmpty(menuIds)) {
            Long roleId = role.getRoleId();
            for (Long menuId : menuIds) {
                RolePerm record = new RolePerm();
                record.setRoleId(roleId);
                record.setPermId(menuId);
                rolePerms.add(record);
            }
        }
        rolePermMapper.removeByRoleId(role.getRoleId());
        if (rolePerms.size() > 0) {
            rolePermMapper.batchSave(rolePerms);
        }
        return result;
    }

    @CacheEvict(value = ROLE_CACHE_NAME,allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int removeRole(Long roleId) {
        if (roleId == null) {
            logger.info("role id is null,remove failed!");
            return 0;
        }
        int count = roleMapper.remove(roleId);
        rolePermMapper.removeByRoleId(roleId);
        return count;
    }

    @Override
    @Cacheable(value = ROLE_CACHE_NAME, key = "methodName + #userId")
    public List<SysRole> listUserRoles(Long userId) {
        if (userId == null) {
            logger.info("userId is null");
            return Collections.emptyList();
        }
        return roleMapper.listUserRoles(userId);
    }

    @Override
    @Cacheable(value = ROLE_CACHE_NAME, key = "#roleId")
    public SysRole getRoleByKey(Long roleId) {
        if (roleId == null) {
            logger.info("roleId is null");
            return null;
        }
        return roleMapper.getByKey(roleId);
    }

    @CacheEvict(value = {ROLE_CACHE_NAME, MENU_CACHE_NAME},allEntries = true)
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateRole(SysRole role) {
        if (role == null) {
            logger.info("role is null,update failed!");
            return 0;
        }
        Long roleId = role.getRoleId();
        if (roleId == null) {
            logger.info("role id is null,update failed!");
            return 0;
        }
        int result = roleMapper.updateByKey(role);
        List<Long> menuIds = role.getMenuIds();
        rolePermMapper.removeByRoleId(roleId);

        List<RolePerm> rms = new ArrayList<>();
        for (Long permId : menuIds) {
            RolePerm rolePerm = new RolePerm();
            rolePerm.setPermId(permId);
            rolePerm.setRoleId(roleId);
            rms.add(rolePerm);
        }
        if (rms.size() > 0) {
            rolePermMapper.batchSave(rms);
        }
        return result;
    }


    @CacheEvict(value = ROLE_CACHE_NAME,allEntries = true)
    @Override
    public int batchRemove(Long[] ids) {
        if (ids.length < 1) {
            logger.info("ids length lt 0, role batch remove failed!");
            return 0;
        }
        return roleMapper.batchRemove(Arrays.asList(ids));
    }

    @Override
    public List<Long> getRolesByUserId(Long userId) {
        return userRoleMapper.getRolesByUserId(userId);
    }

    @Override
    public List<SysRole> listByAll() {
        return roleMapper.listByAll();
    }
}
